/*********************************************************************/
/*                                                                   */
/*      SVPWM Driver                                                 */
/*                                                                   */
/*      Last updated by:  CBS                                        */
/*      Last update date: 12/12/25                                   */
/*      Revision:         0                                          */
/*      Copyright:        DENSO                                      */
/*                                                                   */
/*********************************************************************/

/*********************************************************************/
/* include files                                                     */
/*********************************************************************/
#include"Svpwm.h"
#include"Svpwm_Cfg.h"
#include"Std_Types.h"
#include"Platform_Types.h"
#include"Det.h"
#include"MemMap.h"
#include"MPC5674F_MVx264.h"

/*********************************************************************/
/* Svpwm001: SWS does not cover emulation on GPIO                    */
/* Svpwm065: SWS does not define the code file structure             */
/*********************************************************************/

/****************************************************************************/
/*  defines / data types / structs / unions / macros                        */
/****************************************************************************/
#if SVPWM_DEV_ERROR_DETECT == STD_ON                     /* SVPWM064 */
    #define SVPWM_VALIDATE(_judge,_errorID) \
        if (!(_judge)){ \
            Svpwm_ReportError(_errorID); \
        }
    #define Svpwm_VALIDATE_CHANNEL(_ch) \
            SVPWM_VALIDATE((_ch) <= 32, SVPWM_E_PARAM_CHANNEL )
    #define Svpwm_VALIDATE_INITIALIZED() \
            SVPWM_VALIDATE( Svpwm_ModuleState == SVPWM_STATE_INITIALIZED, SVPWM_E_UNINIT )
    #define Svpwm_VALIDATE_UNINITIALIZED() \
            SVPWM_VALIDATE( Svpwm_ModuleState != SVPWM_STATE_INITIALIZED, SVPWM_E_ALREADY_INITIALIZED)
#else
    #define Svpwm_VALIDATE_CHANNEL(ch)
    #define Svpwm_VALIDATE_INITIALIZED()
    #define Svpwm_VALIDATE_UNINITIALIZED()
#endif /* SVPWM_DEV_ERROR_DETECT */

/*********************************************************************/
/* Module state type definition and initialization                   */
/*********************************************************************/
typedef enum {
    SVPWM_STATE_UNINITIALIZED, SVPWM_STATE_INITIALIZED
} Svpwm_ModuleStateType;

static Svpwm_ModuleStateType 
       Svpwm_ModuleState = SVPWM_STATE_UNINITIALIZED;

/*********************************************************************/
/* Local Functions                                                   */
/*********************************************************************/
void Svpwm_InitChannel(Svpwm_ChannelType ChannelNumber);
void Svpwm_DeInitChannel(Svpwm_ChannelType ChannelNumber);

#if SVPWM_NOTIFICATION_SUPPORTED == STD_ON
/*********************************************************************/
/* TODO: User Callback Function                                      */
/*********************************************************************/
#endif /* SVPWM_NOTIFICATION_SUPPORTED */

/*********************************************************************/
/*  Initialization                  SVPWM095                         */
/*  return      : none                                               */
/*  parameters  : *ConfigPtr                                         */
/*********************************************************************/
void* memcpy(void *dst,const void *src,U4 count);

void Svpwm_Init(const Svpwm_ConfigType* ConfigPtr) {
    Svpwm_ChannelType channel_iterator;  
    U4 i = 0;
    
    for( i = 179; i< 205;i++){
    SIU.PCR[i].B.PA = 0x01;
    SIU.PCR[i].B.IBE = 0;
    SIU.PCR[i].B.OBE = 1;
    } 
    
    Svpwm_VALIDATE_UNINITIALIZED();
    /* Check whether ConfigPtr is NULL */
    #if SVPWM_DEV_ERROR_DETECT == STD_ON
            if (ConfigPtr == NULL) {
                Svpwm_ReportError(SVPWM_E_PARAM_CONFIG);
                return;
            }
    #endif /* SVPWM_DEV_ERROR_DETECT */
    
    #if SVPWM_NOTIFICATION_SUPPORTED == STD_ON
    /*****************************************************************/
    /* TODO: User Callback Function                                  */
    /*****************************************************************/
    #endif
    
    /* Enable Module */
    EMIOS.MCR.B.MDIS = (U4)0;
    
    /* Set Global Prescaler */
    EMIOS.MCR.B.GPRE = (U4)SVPWM_PRESCALER ;
    
    /* Enable Global Prescaler */
    EMIOS.MCR.B.GPREN = (U4)1;
    
    /* Stop channels when in debug mode */
    EMIOS.MCR.B.FRZ = (U4)SVPWM_FREEZE_ENABLE;
    
    /* Use global time base */
    EMIOS.MCR.B.GTBE = (U4)1;
    
    /* Module state transfer */
    Svpwm_ModuleState = SVPWM_STATE_INITIALIZED;
   
    for (channel_iterator = 0; channel_iterator < \
        SVPWM_NUMBER_OF_CHANNELS; channel_iterator++){
        
        Svpwm_ChannelType channel = ConfigPtr->Channels[channel_iterator].channel;
        
        /* Set up HW registers SVPWM 007 062 */
        memcpy((void*) &EMIOS.CH[channel],
                (void*) &ConfigPtr->Channels[channel_iterator].r,
                sizeof(Svpwm_ChannelRegisterType));
        
        #if SVPWM_NOTIFICATION_SUPPORTED == STD_ON
        /*************************************************************/
        /* TODO: User Callback Function                              */
        /*************************************************************/
        #endif /* SVPWM_NOTIFICATION_SUPPORTED */
    }
}

#if SVPWM_DE_INIT_API == STD_ON
/*********************************************************************/
/*  Locol function: DeInitialize Channels                            */
/*********************************************************************/
void Svpwm_DeInitChannel(Svpwm_ChannelType ChannelNumber){
    Svpwm_VALIDATE_CHANNEL(ChannelNumber);
    Svpwm_VALIDATE_INITIALIZED();
    
    EMIOS.CH[ChannelNumber].CADR.R = (U4)0;              /* SVPWM011 */
    EMIOS.CH[ChannelNumber].CCR.B.EDPOL = 1;
    
    #if SVPWM_NOTIFICATION_SUPPORTED == STD_ON
        Svpwm_DisableNotification(ChannelNumber);        /* SVPWM012 */
    #endif /* SVPWM_NOTIFICATION_SUPPORTED */
}


/*********************************************************************/
/*  De-Initialization                SVPWM096                        */
/*  return      : none                                               */
/*  parameters  : none                                               */
/*********************************************************************/
void Svpwm_DeInit() {
    Svpwm_ChannelType channel_iterator;
    
    Svpwm_VALIDATE_INITIALIZED();
    
    for (channel_iterator = 0; channel_iterator < \
         SVPWM_NUMBER_OF_CHANNELS ; channel_iterator++)
    {
        Svpwm_DeInitChannel(channel_iterator);
    }
    
    EMIOS.MCR.B.MDIS = (U4)1;                      /* Disable module */
                                                        /* SVPWM 010 */
    Svpwm_ModuleState = SVPWM_STATE_UNINITIALIZED;
}
#endif /* SVPWM_DE_INIT_API */

#if SVPWM_NOTIFICATION_SUPPORTED == STD_ON
/*********************************************************************/
/*  Disable Notification             SVPWM101                        */
/*  return      : none                                               */
/*  parameters  : CannnelID                                          */
/*********************************************************************/
void Svpwm_DisableNotification(
    Svpwm_ChannelType ChannelNumber){

    Svpwm_VALIDATE_CHANNEL(ChannelNumber);
    Svpwm_VALIDATE_INITIALIZED();
    
    /* Disable flags on this channel */
    EMIOS.CH[ChannelNumber].CCR.B.FEN = (U4)0;

} 

/*********************************************************************/
/*  Enable Notification              SVPWM102                        */
/*  return      : none                                               */
/*  parameters  : CannnelID                                          */
/*              : Notification                                       */
/*********************************************************************/
void Svpwm_EnableNotification( 
    Svpwm_ChannelType ChannelNumber,
    Svpwm_EdgeNotificationType Notification ){
    
    Svpwm_VALIDATE_CHANNEL(ChannelNumber);
    Svpwm_VALIDATE_INITIALIZED();

#if 0
    ChannelRuntimeStruct[ChannelNumber].NotificationState = 
                                       \Notification;
#endif /* 0 */
    /* Enable flags on this channel */
    EMIOS.CH[ChannelNumber].CCR.B.FEN = (U4)1;
    
}

/* Interrupt Currently Not Implemented */
#if 0
static void Svpwm_Isr(void) {
    U4 flagmask = EMIOS.GFR.R;  
    
    for(Svpwm_ChannelType ch = 0; ch < SVPWM_NUMBER_OF_CHANNELS; ch++){
        if(flagmask & (1<<ch)) {
            if (ChannelRuntimeStruct[ch].NotificationRoutine) != NULL
                && EMIOS.CH[ch].CCR.B.FEN) 
                {
                    Svpwm_EdgeNotificationType notification = \
                    ChannelRuntimeStruct[ch].NotificationState;
                        if(notification == SVPWM_BOTH_EDGES || \
                           notification == EMIOS.CH[ch].CSR.B.UCOUT)
                        {
                            ChannelRuntimeStruct[ch].NotificationRoutine();
                        }
                }
                EMIOS.CH[ch].CSR.B.FLAG = (U4)1;
            }
        }
}
#endif/* 0 */
#endif/* SVPWM_NOTIFICATION_SUPPORTED */

#if SVPWM_VERSION_INFO_API == STD_ON

static std_VersionInfoType SVPWM_VersionInfo ={
    (U2)1, 
    (U2)MODULE_ID_SVPWM,
    (U2)SVPWM_INSTANCE_ID,
    
    (U1)SVPWM_SW_MAJOR_VERSION,
    (U1)SVPWM_SW_MINOR_VERSION,
    (U1)SVPWM_SW_PATCH_VERSION,
    
    (U1)SVPWM_AR_MAJOR_VERSION,
    (U1)SVPWM_AR_MINOR_VERSION,
    (U1)SVPWM_AR_PATCH_VERSION 
};

/*********************************************************************/
/*  Get Version Information                SVPWM103                  */
/*  return      : none                                               */
/*  parameters  : versioninfo                                        */
/*********************************************************************/
void Svpwm_GetVersionInfo(
    std_VersionInfoType* versioninfo){
    Svpwm_VALIDATE_INITIALIZED(); 
    
    versioninfo->vendorID = SVPWM_VersionInfo.vendorID;
    versioninfo->moduleID = SVPWM_VersionInfo.moduleID;
    versioninfo->instanceID = SVPWM_VersionInfo.instanceID;
    
    versioninfo->sw_major_version = SVPWM_VersionInfo.sw_major_version;
    versioninfo->sw_minor_version = SVPWM_VersionInfo.sw_minor_version;
    versioninfo->sw_patch_version = SVPWM_VersionInfo.sw_patch_version;
    
    versioninfo->ar_major_version = SVPWM_VersionInfo.ar_major_version;
    versioninfo->ar_minor_version = SVPWM_VersionInfo.ar_minor_version;
    versioninfo->ar_patch_version = SVPWM_VersionInfo.ar_patch_version;
    
}
#endif /* SVPWM_VERSION_INFO_API */

#if SVPWM_UPDATE_DUTYCYCLES_API == STD_ON
/*********************************************************************/
/*  Update Duty Cycles                     SVPWM200                  */
/*  return      : none                                               */
/*  parameters  : DutyCyclesVector                                   */
/*********************************************************************/
void Svpwm_UpdateDutyCycles(
    Svpwm_DutycyclesVectorType DutyCyclesVector){
    
    /* Local variable initialization */
    U4 t_APHASE_LEADING_EDGE = 0x0000;
    U4 t_BPHASE_LEADING_EDGE = 0x0000;
    U4 t_CPHASE_LEADING_EDGE = 0x0000;
    
    U4 t_APHASE_FALLING_EDGE = 0x0000;
    U4 t_BPHASE_FALLING_EDGE = 0x0000;
    U4 t_CPHASE_FALLING_EDGE = 0x0000;
    
    U4 t_APHASE_PERCENTAGE = 0x0000;
    U4 t_BPHASE_PERCENTAGE = 0x0000;
    U4 t_CPHASE_PERCENTAGE = 0x0000;
    
    Svpwm_VALIDATE_INITIALIZED();
    
    /* Update dutycycle into registers of channel 0&1 */
    if(DutyCyclesVector.A_PHASE_DUTYCYCLE == Svpwm_100_Percent || \
       DutyCyclesVector.A_PHASE_DUTYCYCLE == Svpwm_0_Percent){
       
       EMIOS.CH[SVPWM_CHANNEL_0].CADR.R = (U4)0;    /* SVPWM09b */
       EMIOS.CH[SVPWM_CHANNEL_0].CBDR.R = (U4)0;
       EMIOS.CH[SVPWM_CHANNEL_1].CADR.R = (U4)0;
       EMIOS.CH[SVPWM_CHANNEL_1].CBDR.R = (U4)0;
       }
    else{
    t_APHASE_PERCENTAGE = (DutyCyclesVector.A_PHASE_DUTYCYCLE * 100) >> 15; /* /0x80000 = >> 15 */
    t_APHASE_LEADING_EDGE = (SVPWM_PERIOD_MODIFIED * ( 0x64 - t_APHASE_PERCENTAGE) / 0x64) >> 1 ;
    t_APHASE_FALLING_EDGE = SVPWM_PERIOD_MODIFIED - t_APHASE_LEADING_EDGE;
    
    EMIOS.CH[SVPWM_CHANNEL_0].CADR.R = t_APHASE_LEADING_EDGE; /* SVPWM09c */
    EMIOS.CH[SVPWM_CHANNEL_0].CBDR.R = t_APHASE_FALLING_EDGE;
    EMIOS.CH[SVPWM_CHANNEL_1].CADR.R = t_APHASE_LEADING_EDGE - SVPWM_PHASE_DELAY;
    EMIOS.CH[SVPWM_CHANNEL_1].CBDR.R = t_APHASE_FALLING_EDGE;
    }
    
    /* Update dutycycle into registers of channel 2&3 */
    if(DutyCyclesVector.B_PHASE_DUTYCYCLE == Svpwm_100_Percent || \
       DutyCyclesVector.B_PHASE_DUTYCYCLE == Svpwm_0_Percent){
       
       EMIOS.CH[SVPWM_CHANNEL_2].CADR.R = (U4)0;
       EMIOS.CH[SVPWM_CHANNEL_2].CBDR.R = (U4)0;
       EMIOS.CH[SVPWM_CHANNEL_3].CADR.R = (U4)0;
       EMIOS.CH[SVPWM_CHANNEL_3].CBDR.R = (U4)0;
       }
    else{
    t_BPHASE_PERCENTAGE = (DutyCyclesVector.B_PHASE_DUTYCYCLE * 100) >> 15; /* /0x80000 = >> 15 */
    t_BPHASE_LEADING_EDGE = (SVPWM_PERIOD_MODIFIED * ( 0x64 - t_BPHASE_PERCENTAGE) / 0x64) >> 1 ;
    t_BPHASE_FALLING_EDGE = SVPWM_PERIOD_MODIFIED - t_BPHASE_LEADING_EDGE;

    
    EMIOS.CH[SVPWM_CHANNEL_2].CADR.R = t_BPHASE_LEADING_EDGE;
    EMIOS.CH[SVPWM_CHANNEL_2].CBDR.R = t_BPHASE_FALLING_EDGE;
    EMIOS.CH[SVPWM_CHANNEL_3].CADR.R = t_BPHASE_LEADING_EDGE - SVPWM_PHASE_DELAY;
    EMIOS.CH[SVPWM_CHANNEL_3].CBDR.R = t_BPHASE_FALLING_EDGE;
    }
    
    /* Update dutycycle into registers of channel 4&5 */
    if(DutyCyclesVector.C_PHASE_DUTYCYCLE == Svpwm_100_Percent || \
       DutyCyclesVector.C_PHASE_DUTYCYCLE == Svpwm_0_Percent){
       
       EMIOS.CH[SVPWM_CHANNEL_4].CADR.R = (U4)0;
       EMIOS.CH[SVPWM_CHANNEL_4].CBDR.R = (U4)0;
       EMIOS.CH[SVPWM_CHANNEL_5].CADR.R = (U4)0;
       EMIOS.CH[SVPWM_CHANNEL_5].CBDR.R = (U4)0;
       }
    else{
    t_CPHASE_PERCENTAGE = (DutyCyclesVector.C_PHASE_DUTYCYCLE * 100) >> 15; /* /0x80000 = >> 15 */
    t_CPHASE_LEADING_EDGE = (SVPWM_PERIOD_MODIFIED * ( 0x64 - t_CPHASE_PERCENTAGE) / 0x64) >> 1 ;
    t_CPHASE_FALLING_EDGE = SVPWM_PERIOD_MODIFIED - t_CPHASE_LEADING_EDGE;

    EMIOS.CH[SVPWM_CHANNEL_4].CADR.R = t_CPHASE_LEADING_EDGE;
    EMIOS.CH[SVPWM_CHANNEL_4].CBDR.R = t_CPHASE_FALLING_EDGE;
    EMIOS.CH[SVPWM_CHANNEL_5].CADR.R = t_CPHASE_LEADING_EDGE - SVPWM_PHASE_DELAY; 
    EMIOS.CH[SVPWM_CHANNEL_5].CBDR.R = t_CPHASE_FALLING_EDGE;
    }
    
}

#endif /* SVPWM_UPDATE_DUTYCYCLES_API */

/**** End Of File ****************************************************/